<template>
    <n-layout
        id="layout1"
        :content-style="{
            backgroundImage: `url(${backgroundImg})`
        }"
    >
        <n-layout-header
            style="
                height: var(--header-height);
                padding: 0 var(--gap);
                background-color: transparent;
            "
        >
            <n-flex justify="end" align="center">
                <Theme />
            </n-flex>
        </n-layout-header>
        <n-layout-content style="flex: 1; padding-top: 100px">
            <n-card style="width: 420px; max-width: 100%" :bordered="false">
                <Title />
                <n-form
                    ref="formRef"
                    show-feedback
                    size="large"
                    :show-label="false"
                    :model="formState"
                    :rules="formRules"
                    style="margin-top: var(--gap)"
                >
                    <n-form-item path="username">
                        <n-input
                            clearable
                            placeholder="请输入用户名"
                            v-model:value="formState.username"
                        >
                            <template #prefix>
                                <n-icon :component="PersonOutlineTwotone" />
                            </template>
                        </n-input>
                    </n-form-item>
                    <n-form-item path="password">
                        <n-input
                            type="password"
                            clearable
                            placeholder="请输入密码"
                            v-model:value="formState.password"
                        >
                            <template #prefix>
                                <n-icon :component="LockTwotone" />
                            </template>
                        </n-input>
                    </n-form-item>

                    <n-form-item path="captcha" class="captcha">
                        <n-input
                            clearable
                            placeholder="请输入验证码"
                            v-model:value="formState.captcha"
                        >
                            <template #prefix>
                                <n-icon :component="GeneratingTokensTwotone" />
                            </template>

                            <template #suffix>
                                <n-button
                                    class="captcha-btn"
                                    :bordered="false"
                                    :loading="captchaLoading"
                                    :disabled="captchaLoading"
                                    @click="captchaRun"
                                    :style="{
                                        backgroundImage: `url(${captchaLoading && captchaPrev ? captchaPrev : captcha?.image})`,
                                        backgroundSize: 'cover'
                                    }"
                                >
                                    <img
                                        @load="captchaLoaded"
                                        @error="captchaError"
                                        :src="captcha?.image"
                                        style="display: none"
                                    />
                                    <span
                                        v-if="captchaExpired"
                                        style="font-size: 12px; color: #666"
                                        >已过期，请刷新</span
                                    >
                                </n-button>
                            </template>
                        </n-input>
                    </n-form-item>

                    <n-form-item>
                        <n-checkbox v-model:checked="formState.remember">
                            记住账号
                        </n-checkbox>
                    </n-form-item>

                    <n-form-item>
                        <n-button
                            type="primary"
                            block
                            secondary
                            size="large"
                            @click="onSubmit"
                            :loading="loading"
                        >
                            登录
                        </n-button>
                    </n-form-item>
                </n-form>
            </n-card>
        </n-layout-content>
        <n-layout-footer style="background-color: transparent">
            <n-flex justify="center">
                <p>{{ appName }} ©2024 由 咕咕米 提供</p>
            </n-flex>
        </n-layout-footer>
    </n-layout>
</template>

<script setup lang="ts">
import { FormRules, useMessage } from 'naive-ui'
import {
    PersonOutlineTwotone,
    LockTwotone,
    GeneratingTokensTwotone
} from '@vicons/material'
import { nextTick, reactive, ref } from 'vue'
import backgroundImg from '@/assets/images/login-bg.svg'
import { Theme, Title } from '@/components/layout'
import { ICaptcha } from '@/types/global'
import { useRequest } from 'vue-request'
import { authUserLoginCaptcha } from '@/apis/auth/user'
import { onKeyStroke } from '@vueuse/core'
import { IAuthUserLoginParameter } from '@/types/auth/user'
import { AUTH_USER_LOGIN_REMEMBER_KEY } from '@/config/constant'
import { decode, encode } from '@/utils/encrypt'
import { useRouter } from 'vue-router'
import { authUserLogin } from '@/apis/auth/user'
import { initRouter } from '@/router'
import { useAuthUserStore } from '@/store'
import useMessageApi from '@/hooks/useMessageApi'

const appName = import.meta.env.VITE_APP_NAME
const message = useMessage()

/**
 * 验证码
 */
const captchaExpired = ref(false)
const captchaTimer = ref<NodeJS.Timeout>()
const captchaPrev = ref<ICaptcha['image']>()
const {
    run: captchaRun,
    loading: captchaLoading,
    data: captcha
} = useRequest(authUserLoginCaptcha, {
    onSuccess(res) {
        captchaExpired.value = false
        captchaLoading.value = true
        captchaTimer.value = setTimeout(() => {
            captchaExpired.value = true
            formState.captcha = ''
        }, res.expire * 1000)
    },
    onError(e) {
        message.error(e.message)
    }
})

const captchaLoaded = () => {
    captchaLoading.value = false

    if (captcha.value) {
        captchaPrev.value = captcha.value.image
    }

    formState.captcha = ''
}

const captchaError = () => {
    captchaLoading.value = false
    if (captcha.value?.image) {
        message.error('验证码加载失败')
    }
}

/**
 * 表单
 */
const formRef = ref()
const formState = reactive<IAuthUserLoginParameter>({
    username: '',
    password: '',
    captcha: '',
    remember: false
})

const loginConfig = localStorage.getItem(AUTH_USER_LOGIN_REMEMBER_KEY)
if (loginConfig) {
    try {
        const loginConfigDecoded = decode(loginConfig)
        const loginConfigObj = JSON.parse(loginConfigDecoded)
        formState.username = loginConfigObj.username
        formState.password = loginConfigObj.password
        formState.remember = true
    } finally {
        /* continue regardless of error */
    }
}

const formRules: FormRules = {
    username: { required: true },
    password: { required: true },
    captcha: { required: true }
}

const router = useRouter()
const authUserStore = useAuthUserStore()
const { setMessage } = useMessageApi()
const { loading, run } = useRequest(authUserLogin, {
    manual: true,
    async onSuccess(res) {
        // 保存登录状态
        await authUserStore.login(res)

        // 初始化菜单
        await initRouter()

        setMessage({
            type: 'success',
            content: '登录成功'
        })

        nextTick(async () => {
            // 跳转
            const { redirect, ...othersQuery } = router.currentRoute.value.query
            if (redirect) {
                await router.push({
                    name: redirect as string,
                    query: {
                        ...othersQuery
                    }
                })
            } else {
                await router.push('/')
            }
        })

        // 记住账号
        if (formState.remember) {
            const encodeData = encode(
                JSON.stringify({
                    username: formState.username,
                    password: formState.password
                })
            )
            localStorage.setItem(AUTH_USER_LOGIN_REMEMBER_KEY, encodeData)
        } else {
            localStorage.removeItem(AUTH_USER_LOGIN_REMEMBER_KEY)
        }
    },
    onError(e) {
        setMessage({
            type: 'error',
            content: e.message
        })

        captchaRun()
    }
})

function onSubmit() {
    formRef.value
        ?.validate()
        .then(() => {
            setMessage({
                content: '登录中...'
            })
            run(formState)
        })
        .catch((e: Error) => {
            if (e.message) {
                message.error(e.message)
            }
        })
}

onKeyStroke('Enter', () => {
    onSubmit()
})
</script>

<style lang="less" scoped>
#layout1 {
    height: 100%;
    width: 100%;
    background-repeat: no-repeat;
    background-position: center 110px;
    background-size: 100%;

    :deep(.n-layout-scroll-container) {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
}

.n-layout-header {
    .n-flex {
        height: 100%;
    }
}

.captcha {
    :deep(.n-input-wrapper) {
        padding-right: 0;
    }

    .captcha-btn {
        width: 150px;
        height: 38px;
        padding: 0;
    }
}
</style>
